#include <iostream>
#include <random>
#include <thread>

#include "data_codec.h"

// 随机生成数据包
pkt_t generate_random_packet(std::vector<uint8_t>& data_buffer) {
    pkt_t packet;
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dist(1, 255);

    packet.header = 0x55AA;
    packet.seq = dist(gen);
    packet.cmd = dist(gen);
    packet.data_len = dist(gen) % 100; // 随机数据长度
    packet.len = sizeof(pkt_t) + packet.data_len;

    data_buffer.resize(packet.data_len);
    for (auto& byte : data_buffer) {
        byte = dist(gen);
    }

    return packet;
}

// 测试函数，包括粘包和超时情况
void test_codec() {
    DataCodec codec(LogLevel::DEBUG);

    // 1. 模拟粘包数据流：[AA55AA55]
    std::cout << "测试 1: 模拟粘包数据流：[AA55AA55]" << std::endl;
    std::vector<uint8_t> data_stream = {0xAA, 0x55, 0xAA, 0x55};
    std::vector<std::unique_ptr<pkt_t>> decoded_packets = codec.decode(data_stream);

    for (const auto& pkt : decoded_packets) {
        std::cout << "Header: " << std::hex << pkt->header << std::endl;
        std::cout << "Length: " << std::dec << pkt->len << std::endl;
        std::cout << "CRC: " << pkt->crc << std::endl;
        std::cout << "Sequence: " << pkt->seq << std::endl;
        std::cout << "Command: " << pkt->cmd << std::endl;
        std::cout << "Data Length: " << pkt->data_len << std::endl;
        std::cout << "Data: ";
        const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(pkt.get() + 1);
        for (size_t i = 0; i < pkt->data_len; ++i) {
            std::cout << std::hex << static_cast<int>(data_ptr[i]) << " ";
        }
        std::cout << std::endl;
    }

    // 延时，确保触发超时机制
    std::this_thread::sleep_for(std::chrono::milliseconds(1500));

    // 2. 正常多组数据流的测试
    std::cout << "测试 2: 正常多组数据流的测试" << std::endl;
    for (int i = 0; i < 100; ++i) {
        std::vector<uint8_t> data_buffer;
        pkt_t packet = generate_random_packet(data_buffer);

        // 编码
        std::vector<uint8_t> encoded_data = codec.encode(packet, data_buffer.data());

        // 模拟数据流
        std::vector<uint8_t> normal_data_stream;
        normal_data_stream.insert(normal_data_stream.end(), encoded_data.begin(), encoded_data.end());
        decoded_packets = codec.decode(normal_data_stream);

        for (const auto& pkt : decoded_packets) {
            std::cout << "Header: " << std::hex << pkt->header << std::endl;
            std::cout << "Length: " << std::dec << pkt->len << std::endl;
            std::cout << "CRC: " << pkt->crc << std::endl;
            std::cout << "Sequence: " << pkt->seq << std::endl;
            std::cout << "Command: " << pkt->cmd << std::endl;
            std::cout << "Data Length: " << pkt->data_len << std::endl;
            std::cout << "Data: ";
            const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(pkt.get() + 1);
            for (size_t i = 0; i < pkt->data_len; ++i) {
                std::cout << std::hex << static_cast<int>(data_ptr[i]) << " ";
            }
            std::cout << std::endl;
        }
    }

    // 延时，避免超时机制影响
    std::this_thread::sleep_for(std::chrono::milliseconds(1500));

    // 3. 超时测试：模拟接收一个不完整的数据包并等待超时
    std::cout << "测试 3: 超时测试：模拟接收一个不完整的数据包并等待超时" << std::endl;
    std::vector<uint8_t> incomplete_data_stream = {0xAA, 0x55};
    codec.decode(incomplete_data_stream);

    // 等待超过超时时间，触发超时机制
    std::this_thread::sleep_for(std::chrono::milliseconds(1500));

    // 继续发送数据，确保状态机已重置
    std::vector<uint8_t> data_stream_after_timeout = {0xAA, 0x55, 0xAA, 0x55};
    decoded_packets = codec.decode(data_stream_after_timeout);

    for (const auto& pkt : decoded_packets) {
        std::cout << "Header: " << std::hex << pkt->header << std::endl;
        std::cout << "Length: " << std::dec << pkt->len << std::endl;
        std::cout << "CRC: " << pkt->crc << std::endl;
        std::cout << "Sequence: " << pkt->seq << std::endl;
        std::cout << "Command: " << pkt->cmd << std::endl;
        std::cout << "Data Length: " << pkt->data_len << std::endl;
        std::cout << "Data: ";
        const uint8_t* data_ptr = reinterpret_cast<const uint8_t*>(pkt.get() + 1);
        for (size_t i = 0; i < pkt->data_len; ++i) {
            std::cout << std::hex << static_cast<int>(data_ptr[i]) << " ";
        }
        std::cout << std::endl;
    }
}

int main() {
    try {
        test_codec();
    } catch (const std::exception& e) {
        std::cerr << "异常: " << e.what() << std::endl;
    }
    return 0;
}
